//
//  DrawBoardView.m
//  UIBezierPathQuartz2DTest
//
//  Created by Felix Yin on 2019/4/11.
//  Copyright © 2019 Felix Yin. All rights reserved.
//

#import "DrawBoardView.h"
#import "DrawBoardContent.h"

@interface DrawBoardView ()

@property(nonatomic,strong) UIImage *drawImg;
@property(nonatomic,strong) DrawBoardContent *drawContent;

@end

@implementation DrawBoardView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _paintColor = [UIColor blackColor];
        _paintWidth = 10;
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}


//生成一张图片
- (UIImage *) snapImage{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    CGPoint point = [self touchPoint:touches];
    _drawContent = [DrawBoardContent new];
    _drawContent.lineColor = self.paintColor;
    _drawContent.path.lineWidth = self.paintWidth;
    [_drawContent.path moveToPoint:point];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    CGRect drawRect = [self pointDrawRect:touches];
    [self setNeedsDisplayInRect:drawRect];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    CGRect drawRect = [self pointDrawRect:touches];
    [self setNeedsDisplayInRect:drawRect];
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    self.drawImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

- (void)drawRect:(CGRect)rect{
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (self.drawImg) {
        [self.drawImg drawAtPoint:CGPointZero];
    }
    [self.drawContent.lineColor setStroke];
    if (_drawContent.lineColor == [UIColor clearColor]) {
        CGContextSetBlendMode(context, kCGBlendModeClear);
    }else{
        CGContextSetBlendMode(context, kCGBlendModeNormal);
    }
    [self.drawContent.path stroke];
    [super drawRect:rect];
}

- (CGPoint) touchPoint:(NSSet<UITouch *> *)touches{
    UITouch *touch = nil;
    for (UITouch *t in touches) {
        if ([t.view isEqual:self]) {
            touch = t;
            break;
        }
    }
    
    if (touch) {
        return [touch locationInView:self];
    }
    CGPoint point = CGPointMake(-1, -1);
    return point;
}

- (CGPoint) touchPreviousPoint:(NSSet<UITouch *> *)touches{
    UITouch *touch = nil;
    for (UITouch *t in touches) {
        if ([t.view isEqual:self]) {
            touch = t;
            break;
        }
    }
    
    if (touch) {
        return [touch previousLocationInView:self];
    }
    CGPoint point = CGPointMake(-1, -1);
    return point;
}

- (CGRect) pointDrawRect:(NSSet<UITouch *> *)touches{
    CGPoint previousPoint2 = self.drawContent.path.currentPoint;
    CGPoint previousPoint1 = [self touchPreviousPoint:touches];
    CGPoint currentPoint = [self touchPoint:touches];
    CGPoint mid1 = [self middlePoint:previousPoint1 nextPoint:currentPoint];
    [self.drawContent.path addQuadCurveToPoint:mid1 controlPoint:previousPoint1];
    
    CGFloat miniX = [self miniXValue:previousPoint1 point2:previousPoint2 point3:currentPoint];
    CGFloat miniY = [self miniYValue:previousPoint1 point2:previousPoint2 point3:currentPoint];
    CGFloat maxX = [self maxXValue:previousPoint1 point2:previousPoint2 point3:currentPoint];
    CGFloat maxY = [self maxYValue:previousPoint1 point2:previousPoint2 point3:currentPoint];
    CGFloat space = self.paintWidth*0.5+1;
    CGRect drawRect = CGRectMake(miniX-space, miniY-space, maxX-miniX+self.paintWidth, maxY-miniY+self.paintWidth);
    return drawRect;
}

- (CGPoint) middlePoint:(CGPoint) point1 nextPoint:(CGPoint) nextPoint{
    return CGPointMake((point1.x+nextPoint.x)*0.5, (point1.y+nextPoint.y)*0.5);
}

- (CGFloat) miniXValue:(CGPoint) point1 point2:(CGPoint) point2 point3:(CGPoint) point3{
    return MIN(MIN(point1.x, point2.x), point3.x);
}

- (CGFloat) maxXValue:(CGPoint) point1 point2:(CGPoint) point2 point3:(CGPoint) point3{
    return MAX(MAX(point1.x, point2.x), point3.x);
}

- (CGFloat) miniYValue:(CGPoint) point1 point2:(CGPoint) point2 point3:(CGPoint) point3{
    return MIN(MIN(point1.y, point2.y), point3.y);
}

- (CGFloat) maxYValue:(CGPoint) point1 point2:(CGPoint) point2 point3:(CGPoint) point3{
    return MAX(MAX(point1.y, point2.y), point3.y);
}

@end
